/**
 * Copyright (c) 2018-2022, NXOS Development Team
 * SPDX-License-Identifier: Apache-2.0
 * 
 * Contains: process api
 * 
 * Change Logs:
 * Date           Author            Notes
 * 2022-3-19      JasonHu           Init
 * 2022-4-27      JasonHu           add set/get cwd
 * 2022-12-08     JasonHu           add exit call
 */

#ifndef __NXOS_PROCESS_H__
#define __NXOS_PROCESS_H__

#include <nxos/xbook.h>
#include <nxos/clock.h>

#ifdef __cplusplus
extern "C" {
#endif

#define NX_THREAD_NAME_LEN 32

#define NX_THREAD_STATE_INIT      0
#define NX_THREAD_STATE_READY     1
#define NX_THREAD_STATE_RUNNING   2
#define NX_THREAD_STATE_BLOCKED   3
#define NX_THREAD_STATE_EXIT      4

/* thread priority */
#define NX_THREAD_PRIORITY_FLAG     0x1000   /* user thread priority */
#define NX_THREAD_PRIORITY_MASK     0x0FFF   /* user thread priority mask */
#define NX_THREAD_PRIORITY_IDLE     (NX_THREAD_PRIORITY_FLAG | 0)   /* idle thread priority */
#define NX_THREAD_PRIORITY_LOW      (NX_THREAD_PRIORITY_FLAG | 1)   /* low level priority */
#define NX_THREAD_PRIORITY_NORMAL   (NX_THREAD_PRIORITY_FLAG | 3)   /* normal level priority */
#define NX_THREAD_PRIORITY_HIGH     (NX_THREAD_PRIORITY_FLAG | 6)   /* high level priority */
#define NX_THREAD_PRIORITY_MAX      (NX_THREAD_PRIORITY_FLAG | (NX_THREAD_PRIORITY_HIGH + 1))     /* max priority */

#define NX_THREAD_CREATE_NORMAL     0x00 /* thread create with normal flag(no wait, no suspend, running) */   
#define NX_THREAD_CREATE_SUSPEND    0x01 /* thread create with suspend flag(no running) */
#define NX_THREAD_CREATE_WAIT       0x02 /* thread create with wait thread exit(no return, must wait exit) */
#define NX_THREAD_CREATE_DEBUG      0x04 /* thread create to be debugged by gdb */

#define NX_THREAD_DEFAULT_STACK_SZ  8192   /* default thread stack size */

#define NX_TLS_MAX_NR 256 /* max tls count */

typedef struct
{
    NX_Size stackSize;
    NX_U32 schedPriority;
} NX_ThreadAttr;

#define NX_THREAD_ATTR_INIT {NX_THREAD_DEFAULT_STACK_SZ, NX_THREAD_PRIORITY_NORMAL}

void NX_ProcessExit(NX_U32 exitCode);
NX_Solt NX_ProcessLaunch(char *path, NX_U32 flags, NX_U32 *exitCode, char *cmd, char *env);

NX_Error NX_ProcessGetCwd(char * buf, NX_Size length);
NX_Error NX_ProcessSetCwd(char * buf);

NX_Error NX_SoltClose(NX_Solt solt);
NX_Solt NX_SoltCopy(NX_Solt dest, NX_Solt solt);
NX_Solt NX_SoltCopyTo(NX_Solt destThread, NX_Solt srcSolt, NX_Solt destSolt);
NX_Solt NX_SoltInstall(NX_Solt solt, void *object);
NX_Error NX_SoltUninstall(NX_Solt dest, NX_Solt solt);
void *NX_SoltObject(NX_Solt dest, NX_Solt solt);

NX_Solt NX_SnapshotCreate(NX_U32 snapshotType, NX_U32 flags);
NX_Error NX_SnapshotFirst(NX_Solt solt, void * object);
NX_Error NX_SnapshotNext(NX_Solt solt, void * object);

NX_Error NX_ThreadSleep(NX_UArch microseconds);
NX_Solt NX_ThreadCreate(NX_ThreadAttr * attr, NX_U32 (*handler)(void *), void * arg, NX_U32 flags);
void NX_ThreadExit(NX_U32 exitCode);
NX_Error NX_ThreadSuspend(NX_Solt solt);
NX_Error NX_ThreadResume(NX_Solt solt);
NX_Error NX_ThreadWait(NX_Solt solt, NX_U32 * exitCode);
NX_Error NX_ThreadTerminate(NX_Solt solt, NX_U32 exitCode);
void NX_ThreadYield(void);

NX_U32 NX_ThreadGetId(NX_Solt solt);
NX_U32 NX_ThreadGetCurrentId(void);
NX_Solt NX_ThreadGetCurrent(void);
NX_U32 NX_ThreadGetProcessId(NX_Solt solt);

NX_Error NX_ThreadAttrInit(NX_ThreadAttr * attr, NX_Size stackSize, NX_U32 schedPriority);

int NX_TlsAlloc(void);
NX_Error NX_TlsFree(int index);
NX_Error NX_TlsSetValue(int index, void * value);
void * NX_TlsGetValue(int index);
void NX_TlsSetExtension(void * data);
void * NX_TlsGetExtension(void);
void * NX_TlsGetExtensionAddr(void);
void NX_TlsClearData(void);

#define NX_MUTEX_ATTR_LOCKED 0x01

NX_Solt NX_MutexCreate(NX_U32 attr);
NX_Error NX_MutexDestroy(NX_Solt solt);
NX_Error NX_MutexAcquire(NX_Solt solt);
NX_Error NX_MutexTryAcquire(NX_Solt solt);
NX_Error NX_MutexRelease(NX_Solt solt);
NX_Error NX_MutexAcquirable(NX_Solt solt);

NX_Solt NX_SemaphoreCreate(NX_IArch value);
NX_Error NX_SemaphoreDestroy(NX_Solt solt);
NX_Error NX_SemaphoreWait(NX_Solt solt);
NX_Error NX_SemaphoreTryWait(NX_Solt solt);
NX_Error NX_SemaphoreSignal(NX_Solt solt);
NX_Error NX_SemaphoreSignalAll(NX_Solt solt);
NX_IArch NX_SemaphoreGetValue(NX_Solt solt);

typedef void (*NX_ExitCallHandler)(void);

#define NX_EXIT_CALL_NR 32

NX_Error NX_ExitCallRegister(NX_ExitCallHandler handler);

NX_Solt NX_ConditionCreate(NX_U32 attr);
#define NX_ConditionDestroy(solt) NX_SoltClose(solt)
NX_Error NX_ConditionWait(NX_Solt solt, NX_Solt mutexSolt);
NX_Error SysConditionWaitTimeout(NX_Solt solt, NX_Solt mutexSolt, NX_TimeVal tv);
NX_Error NX_ConditionSignal(NX_Solt solt);
NX_Error NX_ConditionBroadcast(NX_Solt solt);

#ifdef __cplusplus
}
#endif

#endif  /* __NXOS_PROCESS_H__ */
